﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Game.Global.Helper;

namespace Game
{
    /// <summary>
    /// Unity 配置
    /// </summary>
    class UConfig
    {
        /// <summary>
        /// 配置的目录
        /// </summary>
        const string C_ConfigFolder = "Config";

        /// <summary>
        /// 默认的配置文件名
        /// </summary>
        const string C_DefaultConfig = "DefaultConfig";

        /// <summary>
        /// 是否可以修改资源中的Config
        /// </summary>
        bool C_CanEditResourceConfig =
#if UNITY_EDITOR
            true;
#else
        false;
#endif

        static UConfig _defaultConfig = null;

        /// <summary>
        /// 获取默认的“Config”文件配置
        /// </summary>
        public static UConfig DefaultConfig
        {
            get
            {
                if (_defaultConfig == null)
                {
                    _defaultConfig = new UConfig(C_DefaultConfig, true);
                }

                return _defaultConfig;
            }
        }

        /// <summary>
        /// 此Config文件是否在Resources中
        /// </summary>
        bool m_isInResources;
        string m_fileName;
        Dictionary<string, object> m_dictContent = null;

        /// <summary>
        /// 构造方法，读入某文件作为config
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isInResources">配置文件是否在Resources文件夹中</param>
        private UConfig(string fileName, bool isInResources)
        {
            m_fileName = fileName;
            m_isInResources = isInResources;

            ReadConfig();
        }

        #region static part
        /// <summary>
        /// 读取新的Config
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isInResources">配置文件是否在Resources文件夹中</param>
        /// <returns></returns>
        public static UConfig GetConfig(string fileName, bool isInResources = true)
        {
            return new UConfig(fileName, isInResources);
        }

        /// <summary>
        /// 为某个类读取Config
        /// </summary>
        /// <param name="scriptType">调用者类</param>
        /// <param name="isInResources">配置文件是否在Resources文件夹中</param>
        /// <returns></returns>
        public static UConfig GetConfig(Type scriptType, bool isInResources = true)
        {
            return new UConfig(scriptType.Name, isInResources);
        }

        #endregion

        #region Public member function part

        /// <summary>
        /// 获得string类型的值，无则报错：
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetString(string key)
        {
            return GetValue<string>(key);
        }

        /// <summary>
        /// 获得对应数值类型，无则报错：
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetValue<T>(string key, T defaultVal = default(T))
        {
            if (!m_dictContent.ContainsKey(key))
            {
#if UNITY_EDITOR
                //编辑器模式下，直接将默认值存入该配置：
                Debug.LogWarning(string.Format("Config key {0} not find in file {1}, it will be add.", key, m_fileName));
                SetValue(key, defaultVal);
#endif
                return defaultVal;
            }
            else
            {
                //内置方法，会调用对应的ToInt32()/ToLong()等方法
                return (T)Convert.ChangeType(m_dictContent[key], typeof(T));
            }
        }

        /// <summary>
        /// 只允许自定义的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetValue<T>(string key, T value)
        {
#if UNITY_EDITOR
            if (!C_CanEditResourceConfig)
            {
                AssertEditable();
            }
#endif
            m_dictContent[key] = value;

            SaveConfig();

            Debug.Log("配置已经保存，但需要重新切换编辑器窗口以刷新文件");
        }


        private void ReadConfig()
        {
            //配置文件是否在Resources中的：
            if (IsConfigInResources())
            {
                //直接获取Resource中的
                m_dictContent = FileHelper.LoadResource<Dictionary<string, object>>(C_ConfigFolder, m_fileName);
            }
            else
            {
                //可读可写目录的
                m_dictContent = FileHelper.ReadFile<Dictionary<string, object>>(C_ConfigFolder, m_fileName);
            }

            //--默认的JsonUtility对于Dictionary不起作用
            //m_dictContent = JsonUtility.FromJson<Dictionary<string,string>>(configContent);

            if (m_dictContent == null)
            {
                m_dictContent = new Dictionary<string, object>();
            }
        }

        private void SaveConfig()
        {
            //Debug.Log("Serialized:" + fileContent);
            if (IsConfigInResources())
            {
#if UNITY_EDITOR
                FileHelper.Editor_SaveResource(C_ConfigFolder, m_fileName, m_dictContent, true);
#endif
            }
            else
            {
                FileHelper.SaveObjToFile(C_ConfigFolder, m_fileName, m_dictContent);
            }
        }

        /// <summary>
        /// 是否是可更改的Config，不可更改则将抛出异常
        /// </summary>
        private void AssertEditable()
        {
            if (IsConfigInResources())
            {
                throw new NotImplementedException("Not allowed to edit default config ");
            }
        }

        private bool IsConfigInResources()
        {
            return m_isInResources;
        }
        #endregion
    }

}
